<template>
  <div
    style="
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100%;
      height: 100%;
      position: relative;
      overflow-y: auto;
    "
  >
    <div class="tool" v-if="isToolDisplay">
      <div @click="handleClickTool('copy')" title="复制">
        <i class="el-icon-document-copy"></i>
      </div>
      <div @click="handleClickTool('paste')" title="粘贴">
        <i class="el-icon-document"></i>
      </div>
      <div @click="handleClickTool('delete')" title="删除">
        <i class="el-icon-delete"></i>
      </div>
    </div>
    <div class="box">
      <canvas id="canvasId" style="border: 1px solid #e4e4e4"></canvas>
    </div>
    <div class="scaleZoom">
      <div @click="handleTuneScale('-')">
        <i class="el-icon-minus"></i>
      </div>
      <div>{{ (scaleZoom * 1000000) / 10000 }} %</div>
      <div @click="handleTuneScale('+')">
        <i class="el-icon-plus"></i>
      </div>
    </div>
  </div>
</template>

<script>
import { fabric } from "fabric";
import jsonData from "./initjson.json";
import { initAligningGuidelines } from "./boxleftdata";
import Table from "./table";
export default {
  data() {
    return {
      isToolDisplay: false, // 是否选中了元素, tool工具栏才会展示
      canvas: null,
      jsonData: jsonData,
      canvasBackgroundColor: "#f7f7f7",
      selectedObject: null, // 当前选中的元素对象
      canvasWidth: 1336, // 初始画布宽度
      canvasHeight: 623, // 初始画布高度
      menuPosition: "", // 右键显示位置
      scaleZoom: 0.4, // 缩放比例
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.initCanvas();
      Table(this.canvas);
    });
  },
  methods: {
    // 工具栏
    handleClickTool(val) {
      if (val === "copy") {
        this.copyEl();
      } else if (val === "paste") {
        this.pasteEl();
      } else if (val === "delete") {
        this.delEl();
      }
      this.isToolDisplay = false;
    },
    // 点击调整缩放
    handleTuneScale(val) {
      const scaleZoom = this.scaleZoom * 100;
      // 边界情况
      if (val === "-" && (scaleZoom * 100000) / 100000 === 10) {
        this.scaleZoom = 0.1;
        this.setCanvasWidth();
        return;
      }
      if (val === "+" && (scaleZoom * 100000) / 100000 === 100) {
        this.scaleZoom = 1;
        this.setCanvasWidth();
        return;
      }
      if (val === "+" && (scaleZoom * 100000 + 500000) / 100000 > 100) {
        this.scaleZoom = 1;
        this.setCanvasWidth();
        return;
      }
      if (val === "-" && (scaleZoom * 100000 - 500000) / 100000 < 10) {
        this.scaleZoom = 0.1;
        this.setCanvasWidth();
        return;
      }
      // 以上边界情况都不是的情况下, 就可以加加减减
      if (val === "+") {
        const num = (scaleZoom * 100000 + 500000) / 100000;
        this.scaleZoom = +Number(num).toFixed(0) / 100;
      }
      if (val === "-") {
        const num = (scaleZoom * 100000 - 500000) / 100000;
        this.scaleZoom = +Number(num).toFixed(0) / 100;
      }
      this.setCanvasWidth();
    },
    // 缩放设置canvas大小
    setCanvasWidth() {
      // 计算缩放比例
      var scaleRatio = this.scaleZoom; // 缩放比例为0.5，即将画布调整为原来的一半大小
      // 调整画布的大小
      var newWidth = this.canvasWidth * scaleRatio;
      var newHeight = this.canvasHeight * scaleRatio;
      this.canvas.setDimensions({ width: newWidth, height: newHeight });
    },
    // 复制功能
    copyEl() {
      const activeObj = this.canvas.getActiveObject();
      if (!activeObj) return; // 确保有选中对象

      activeObj.clone((cloned) => {
        // 存储原始位置并重置粘贴计数
        this.clipboard = {
          obj: cloned,
          originalLeft: cloned.left,
          originalTop: cloned.top,
        };
        this.pasteCount = 0;
      });
      this.canvas.renderAll();
    },

    // 粘贴功能
    pasteEl() {
      if (!this.clipboard) return;

      this.pasteCount++; // 递增粘贴次数
      this.clipboard.obj.clone((clonedObj) => {
        clonedObj.set({
          left: this.clipboard.originalLeft + 20 * this.pasteCount,
          top: this.clipboard.originalTop + 20 * this.pasteCount,
          evented: true,
        });

        this.canvas.discardActiveObject();
        this._addClonedObject(clonedObj);
        this.canvas.setActiveObject(clonedObj);
        this.canvas.requestRenderAll();
      });
    },
    // 处理克隆对象添加到画布
    _addClonedObject(clonedObj) {
      if (clonedObj.type === "activeSelection") {
        clonedObj.canvas = this.canvas;
        clonedObj.forEachObject((obj) => this.canvas.add(obj));
        clonedObj.setCoords();
      } else {
        this.canvas.add(clonedObj);
      }
    },
    // 删除元素
    delEl() {
      // 删除当前选中元素
      this.canvas.remove(this.selectedObject);
      this.canvas.requestRenderAll();
    },
    createTable() {
      const options = {
        canvas: this.canvas,
        left: 0,
        top: 0,
        borderWidth: 1,
        rowHeights: [25, 25, 25, 25, 25, 25],
        columnWidths: [70, 195],
        cells: [
          {
            row: 0,
            col: 0,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 0,
            col: 1,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 1,
            col: 0,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 1,
            col: 1,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 2,
            col: 0,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 2,
            col: 1,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 3,
            col: 0,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 3,
            col: 1,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 4,
            col: 0,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
          {
            row: 4,
            col: 1,
            rowSpan: 0,
            colSpan: 0,
            content: "",
          },
        ],
      };
      const canvas = this.canvas;
      const center = canvas.getCenter();
      const table = new fabric.Table(options);
      table.set("left", center.left - table.width / 2);
      table.set("top", center.top - table.height / 2);
      canvas.add(table);
    },
    // 插入表格
    addTableInit() {
      // 创建表格的行和列
      this.createTable();
    },
    // 加载json数据回显页面
    addJsonInit() {
      this.canvas.clear(); // 清空当前画布
      this.canvas.loadFromJSON(
        this.jsonData,
        this.canvas.renderAll.bind(this.canvas)
      );
    },
    // 初始化画布
    initCanvas() {
      this.canvasHeight = window.outerHeight - 50;
      console.log(window.outerHeight);
      this.canvas = new fabric.Canvas("canvasId", {
        backgroundColor: this.canvasBackgroundColor,
        width: this.canvasWidth * this.scaleZoom,
        height: this.canvasHeight * this.scaleZoom,
        fireRightClick: true, // 启用右键，button的数字为3
        stopContextMenu: true, // 禁止默认右键菜单
        selection: false, // 禁用默认选择
      });
      this.canvas.setBackgroundColor(
        "#ffffff",
        this.canvas.renderAll.bind(this.canvas)
      ); // 设置背景颜色为浅灰色
      this.canvas.selection = false; // 禁止选择整个画布上的对象（可选）
      let deleteImg = document.createElement("img");
      deleteImg.src =
        "https://www.chuangkit.com/designdist/rotate.svg?b4b96237716b02445af3fe3be560bf52";

      function renderIcon(icon) {
        return function renderIcon(
          ctx,
          left,
          top,
          styleOverride,
          fabricObject
        ) {
          let size = this.cornerSize;
          ctx.save();
          ctx.translate(left, top);
          ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
          ctx.drawImage(icon, -size / 2, -size / 2, size, size);
          ctx.restore();
        };
      }

      function renderIcon2() {
        return function renderIcon(
          ctx,
          left,
          top,
          styleOverride,
          fabricObject
        ) {
          let size = this.cornerSize;
          ctx.save();
          ctx.translate(left, top);
          ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));

          ctx.fillStyle = "while";
          ctx.fillRect(-size / 2, -size / 2, size, size);
          ctx.strokeStyle = "#c0c0c0";
          ctx.strokeRect(-size / 2, -size / 2, size, size);
          ctx.restore();
        };
      }
      fabric.Object.prototype.controls.mtr.render = renderIcon(deleteImg);
      fabric.Object.prototype.controls.mtr.cornerSize = 14;
      fabric.Object.prototype.controls.mtr.withConnection = false;
      fabric.Object.prototype.controls.mtr.offsetY = 20;
      fabric.Object.prototype.controls.mtr.x = 0;
      fabric.Object.prototype.controls.mtr.y = 0.5;

      fabric.Object.prototype.controls.mt.render = renderIcon2();
      fabric.Object.prototype.controls.mt.cornerSize = 10;
      fabric.Object.prototype.controls.mb.render = renderIcon2();
      fabric.Object.prototype.controls.mb.cornerSize = 10;
      fabric.Object.prototype.controls.mr.render = renderIcon2();
      fabric.Object.prototype.controls.mr.cornerSize = 10;
      fabric.Object.prototype.controls.ml.render = renderIcon2();
      fabric.Object.prototype.controls.ml.cornerSize = 10;
      fabric.Object.prototype.set({
        borderColor: "blue",
        cornerColor: "white", //激活状态角落图标的填充颜色
        cornerStrokeColor: "#c0c0c0", //激活状态角落图标的边框颜色
        borderOpacityWhenMoving: 1,
        borderScaleFactor: 1,
        cornerSize: 10,
        cornerStyle: "circle", //rect,circle
        centeredScaling: false, //角落放大缩小是否是以图形中心为放大原点
        centeredRotation: true, //旋转按钮旋转是否是左上角为圆心旋转
        transparentCorners: false, //激活状态角落的图标是否透明
        rotatingPointOffset: 5, //旋转距旋转体的距离
        lockUniScaling: false, //只显示四角的操作
        hasRotatingPoint: true, //是否显示旋转按钮
        selectionDashArray: [5, 5],
      });
      initAligningGuidelines(this.canvas);
      this.canvas.on("mouse:down", this.canvasOnMouseDown);
      // 监听点击
      this.canvas.on("mouse:up", (e) => {
        if (e.target) {
          this.selectedObject = e.target;
          this.isToolDisplay = true;
        } else {
          this.selectedObject = null;
        }
      });
    },
    // 新增集合图形
    addHowMuch(val) {
      let fontTxt = "";
      if (val === "圆形") {
        // 创建圆形
        const circle = new fabric.Circle({
          left: 200,
          top: 200,
          radius: 50,
          fill: "red",
          opacity: 0.6,
          hasBorders: true,
          hasControls: true,
          selectable: true,
        });
        fontTxt = circle;
      } else if (val === "正方形") {
        // 创建矩形
        const rect = new fabric.Rect({
          left: 50,
          top: 50,
          width: 100,
          height: 100,
          fill: "blue",
          opacity: 0.8,
          hasBorders: true,
          hasControls: true,
          selectable: true,
        });
        fontTxt = rect;
      } else {
        const longrect = new fabric.Rect({
          left: 50,
          top: 50,
          width: 200,
          height: 100,
          fill: "blue",
          opacity: 0.8,
          hasBorders: true,
          hasControls: true,
          selectable: true,
        });
        fontTxt = longrect;
      }
      // 添加图形到画布
      this.canvas.add(fontTxt);
    },
    // 新增图片
    addImage(url) {
      console.log(url, "图片");
      fabric.Image.fromURL(
        url,
        (img) => {
          // 获取画布的宽高
          const canvasWidth = this.canvas.getWidth();
          const canvasHeight = this.canvas.getHeight();
          const maxWidth = canvasWidth * 0.6;
          const maxHeight = canvasHeight * 0.3;
          let scale = Math.min(maxWidth / img.width, maxHeight / img.height);
          img.scale(scale).set({
            left: (canvasWidth - img.width * scale) / 2,
            top: (canvasHeight - img.height * scale) / 2,
            scaleWidth: img.width * scale,
            scaleHeight: img.height * scale,
          });
          this.canvas.add(img);
          // 重新渲染画布以显示新添加的图片
          this.canvas.renderAll();
        },
        { crossOrigin: "anonymous" }
      );
    },
    addTxt(txt) {
      const text = new fabric.IText(txt, {
        left: 100,
        top: 100,
        fontSize: 30,
        fontFamily: "arial",
        fill: "#333",
        originX: "left",
        originY: "top",
      });
      this.canvas.add(text);
    },
    // 生成json
    exportCanvasAsJSON() {
      console.log("触发了");
      const jsonData = this.canvas.toJSON([
        "selectable",
        "evented",
        "is_background",
        "scaleX",
        "scaleY",
        "scaleWidth",
        "scaleHeight",
      ]);
      const jsonString = JSON.stringify(jsonData, null, 2);
      const blob = new Blob([jsonString], { type: "text/json" });
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = "canvas_data.json";
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    },
    // 生成图片
    exportCanvasAsImage() {
      const imageUrl = this.canvas.toDataURL({
        format: "png",
        quality: 0.8,
      });
      const a = document.createElement("a");
      a.href = imageUrl;
      a.download = "canvas_image.png";
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(imageUrl);
    },
  },
};
</script>

<style lang="scss" scoped>
.box {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.menu-x {
  width: 80px;
  position: absolute;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
  text-align: center;

  div {
    box-sizing: border-box;
    padding: 4px 8px;
    border-bottom: 1px solid #fff;
    cursor: pointer;

    &:hover {
      background-color: antiquewhite;
    }

    &:first-child {
      border-top-left-radius: 4px;
      border-top-right-radius: 4px;
    }

    &:last-child {
      border-bottom: none;
      border-bottom-left-radius: 4px;
      border-bottom-right-radius: 4px;
    }
  }
}

.scaleZoom {
  position: absolute;
  right: 20px;
  bottom: 0px;
  background-color: #fff;
  width: 120px;
  height: 40px;
  box-shadow: 0 0 4px 0 #ccc;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px;
  box-sizing: border-box;
  color: #202020;
  font-size: 16px;
  font-weight: 700;
  border-radius: 4px;
  cursor: pointer;
}
.tool {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 0px;
  background-color: #fff;
  width: 120px;
  height: 40px;
  box-shadow: 0 0 4px 0 #ccc;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px;
  box-sizing: border-box;
  color: #202020;
  font-size: 16px;
  font-weight: 700;
  border-radius: 4px;
  cursor: pointer;
  z-index: 999;
}

::-webkit-scrollbar {
  display: none;
}
</style>
